package uk.co.q3c.deplan.server.unit.dao;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.Test;

import uk.co.q3c.deplan.client.dao.DiscardedState;
import uk.co.q3c.deplan.client.domain.DomainObject;
import uk.co.q3c.deplan.client.domain.dag.ChangeInvalidException;
import uk.co.q3c.deplan.client.domain.dag.CycleDetectedException;
import uk.co.q3c.deplan.client.domain.dag.DAG;
import uk.co.q3c.deplan.client.domain.dag.SharedStructureChangeLog;
import uk.co.q3c.deplan.client.domain.resource.IndividualResource;
import uk.co.q3c.deplan.client.domain.resource.PersistenceReferenceException;
import uk.co.q3c.deplan.client.domain.task.BaseTask;
import uk.co.q3c.deplan.server.dao.DomainDao;
import uk.co.q3c.deplan.server.dao.DomainDao_BigT;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

@Test
public class Dao_UT extends LocalDatastoreTestCase {

	transient protected final Logger logger = Logger.getLogger(getClass().getName());

	@Override
	protected void beforeClass() throws Exception {
		super.beforeClass();
	}

	@Override
	protected void beforeMethod() throws Exception {
		super.beforeMethod();
	}

	@Override
	protected void afterMethod() throws Exception {
		connection.closeSession();
		super.afterMethod();
	}

	public void countSimpleDomain() {
		SimpleDomainObject tob1 = new SimpleDomainObject(connection, 33);
		SimpleDomainObject tob2 = new SimpleDomainObject(connection, 34);
		testdao.save(tob1);
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, tob1.getClass()), 1);
		// Assert.assertEquals(tob1.getSaasCustomerId(),
		// connection.getSaasCustomerId());
		// are the saas values set?
		// Assert.assertEquals(tob1.getSaasInstanceId(),
		// connection.getSaasInstanceId());
		testdao.save(tob2);
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, tob1.getClass()), 2);

	}

	public void countComplexDomain() {
		ComplexDomainObject tob1 = new ComplexDomainObject(33);
		ComplexDomainObject tob2 = new ComplexDomainObject(34);
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		tob1.setSimple(sdo1);
		testdao.save(tob1);
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, tob1.getClass()), 1);
		// Assert.assertEquals(tob1.getSaasCustomerId(),
		// connection.getSaasCustomerId());
		testdao.save(tob2);
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, tob1.getClass()), 2);
	}

	public void discard() throws CycleDetectedException, ChangeInvalidException, PersistenceReferenceException {
		// create 4 objects 3 with the same property value to make sure they
		// would all be
		// returned then change discard status and check returned results
		// 4th object should have property with different value, to make sure
		// "where" part of filter is correct
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		testdao.save(sdo3);
		SimpleDomainObject sdo4 = new SimpleDomainObject(connection, 102);
		testdao.save(sdo4);

		// Select where
		// check all three query variations
		List<SimpleDomainObject> resultsAny = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(resultsAny.size(), 3);
		List<SimpleDomainObject> resultsOnlyDiscards = testdao.findList(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertNull(resultsOnlyDiscards);
		List<SimpleDomainObject> resultsNoDiscards = testdao.findList(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(resultsNoDiscards.size(), 3);

		// count (remember there is no where - sdo4 should be returned as well
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class), 4);
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 4);
		Assert.assertEquals(testdao.count(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class), 0);

		// select key where
		List<Key<SimpleDomainObject>> resultsKeyAny = testdao.findKeysList(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "intValue",
				101);
		Assert.assertEquals(resultsKeyAny.size(), 3);
		List<Key<SimpleDomainObject>> resultsKeyOnlyDiscards = testdao.findKeysList(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class,
				"intValue", 101);
		Assert.assertEquals(resultsKeyOnlyDiscards.size(), 0);
		List<Key<SimpleDomainObject>> resultsKeyNoDiscards = testdao.findKeysList(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class,
				"intValue", 101);
		Assert.assertEquals(resultsKeyNoDiscards.size(), 3);

		// count where
		Assert.assertEquals(testdao.countWhere(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101), 3);
		Assert.assertEquals(testdao.countWhere(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class, "intValue", 101), 0);
		Assert.assertEquals(testdao.countWhere(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101), 3);

		// discard one object an repeat
		sdo1.setDiscarded(true);
		testdao.save(sdo1);
		resultsAny = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(resultsAny.size(), 3);
		resultsOnlyDiscards = testdao.findList(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(resultsOnlyDiscards.size(), 1);
		resultsNoDiscards = testdao.findList(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(resultsNoDiscards.size(), 2);

		// count (remember there is no where - sdo4 should be returned as well
		Assert.assertEquals(testdao.count(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class), 4);
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 3);
		Assert.assertEquals(testdao.count(DiscardedState.ONLY_DISCARDED, SimpleDomainObject.class), 1);

	}

	/**
	 * Select first of 3 objects with a specified property value
	 */
	public void selectFirst() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);

		SimpleDomainObject sdo4 = testdao.findFirstWhere(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(sdo1.getTag(), sdo4.getTag());
	}

	public void selectAll() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);

		List<SimpleDomainObject> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class);
		Assert.assertEquals(results.size(), 3);
	}

	public void selectAll_withSubclass() {
		SubclassObject sdo1 = new SubclassObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SubclassObject sdo2 = new SubclassObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SubclassObject sdo3 = new SubclassObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);

		List<SubclassObject> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SubclassObject.class);
		Assert.assertEquals(results.size(), 3);
	}

	public void selectAll_withSubSubclass() {
		SubSubclassObject sdo1 = new SubSubclassObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SubSubclassObject sdo2 = new SubSubclassObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SubSubclassObject sdo3 = new SubSubclassObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);

		List<SubSubclassObject> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SubSubclassObject.class);
		Assert.assertEquals(results.size(), 3);
	}

	public void selectAll_withSubSubSubclass() {
		SubSubSubclassObject sdo1 = new SubSubSubclassObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SubSubSubclassObject sdo2 = new SubSubSubclassObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SubSubSubclassObject sdo3 = new SubSubSubclassObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);

		List<SubSubSubclassObject> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, SubSubSubclassObject.class);
		Assert.assertEquals(results.size(), 3);
	}

	public void selectWhereWithCollection() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 102);
		sdo3.setTag("3");
		testdao.save(sdo3);
		ComplexDomainObject cdo1 = new ComplexDomainObject();
		cdo1.setIntValue(101);
		testdao.save(cdo1);
		List<Class<? extends DomainObject>> classes = new ArrayList<Class<? extends DomainObject>>();
		classes.add(SimpleDomainObject.class);
		classes.add(ComplexDomainObject.class);
		List<? extends DomainObject> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, classes, "intValue", 101);
		Assert.assertEquals(results.size(), 3);
		cdo1.setIntValue(102);
		testdao.save(cdo1);
		results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, classes, "intValue", 101);
		Assert.assertEquals(results.size(), 2);
	}

	public void selectAll_AbstractTask() {
		BaseTask sdo1 = new BaseTask(connection);
		sdo1.setName("1");
		testdao.save(sdo1);
		BaseTask sdo2 = new BaseTask(connection);
		sdo2.setName("2");
		testdao.save(sdo2);
		BaseTask sdo3 = new BaseTask(connection);
		sdo3.setName("3");
		testdao.save(sdo3);

		List<BaseTask> results = testdao.findList(DiscardedState.INCLUDE_DISCARDED, BaseTask.class);
		Assert.assertEquals(results.size(), 3);
	}

	// public void selectFirstWithCollection() {
	// SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
	// sdo1.setTag("1");
	// testdao.save(sdo1);
	// SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
	// sdo2.setTag("2");
	// testdao.save(sdo2);
	// SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 102);
	// sdo3.setTag("3");
	// testdao.save(sdo3);
	// ComplexDomainObject cdo1 = new ComplexDomainObject();
	// cdo1.setIntValue(101);
	// testdao.save(cdo1);
	// List<Class<? extends DomainObject>> classes = new ArrayList<Class<?
	// extends DomainObject>>();
	// classes.add(SimpleDomainObject.class);
	// classes.add(ComplexDomainObject.class);
	//
	// SimpleDomainObject result = (SimpleDomainObject)
	// testdao.findFirst(DiscardedState.INCLUDE_DISCARDED, classes, "intValue",
	// 101);
	// Assert.assertEquals(result.getIntValue(), 101);
	//
	// // now do complex first
	// classes = new ArrayList<Class<? extends DomainObject>>();
	// classes.add(ComplexDomainObject.class);
	// classes.add(SimpleDomainObject.class);
	// Assert.assertTrue(testdao.count(DiscardedState.INCLUDE_DISCARDED,
	// ComplexDomainObject.class) > 0);
	// ComplexDomainObject result2 = (ComplexDomainObject)
	// testdao.findFirst(DiscardedState.INCLUDE_DISCARDED, classes, "intValue",
	// 101);
	// Assert.assertEquals(result2.getIntValue(), 101);
	//
	// }

	public void deleteAll() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 3);
		testdao.deleteAllSimple();
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 0);
	}

	public void deleteWhere() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);
		Assert.assertEquals(testdao.countWhere(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101), 3);
		Assert.assertEquals(testdao.countWhere(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "tag", "3"), 1);
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 3);
		testdao.deleteTagged(DiscardedState.EXCLUDE_DISCARDED, "3");
		Assert.assertEquals(testdao.count(DiscardedState.EXCLUDE_DISCARDED, SimpleDomainObject.class), 2);
	}

	public void getObjectsFromKeys() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("1");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);
		SimpleDomainObject sdo4 = new SimpleDomainObject(connection, 101);
		sdo4.setTag("4");
		testdao.save(sdo4);

		// deliberately miss one
		List<Key<? extends DomainObject>> keys = new ArrayList<Key<? extends DomainObject>>();
		keys.add(keyFor(sdo1));
		keys.add(keyFor(sdo2));
		keys.add(keyFor(sdo3));
		List<? extends DomainObject> objects = testdao.getListOf(keys);
		Assert.assertEquals(objects.size(), 3);

	}

	public void selectKeysWhere() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("2");
		testdao.save(sdo1);
		SimpleDomainObject sdo2 = new SimpleDomainObject(connection, 101);
		sdo2.setTag("2");
		testdao.save(sdo2);
		SimpleDomainObject sdo3 = new SimpleDomainObject(connection, 101);
		sdo3.setTag("3");
		testdao.save(sdo3);
		List<Key<SimpleDomainObject>> results = testdao.findKeys(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "intValue", 101);
		Assert.assertEquals(results.size(), 3);
		Assert.assertEquals(results.get(0)
				.getClass()
				.getName(), Key.class.getName());
		results = testdao.findKeys(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "tag", "2");
		Assert.assertEquals(results.size(), 2);
		results = testdao.findKeys(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "tag", "3");
		Assert.assertEquals(results.size(), 1);
		results = testdao.findKeys(DiscardedState.INCLUDE_DISCARDED, SimpleDomainObject.class, "tag", "1");
		Assert.assertEquals(results.size(), 0);
	}

	public void getFromKeyClassandKey() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("2");
		testdao.save(sdo1);
		Key<SimpleDomainObject> key = keyFor(sdo1);
		SimpleDomainObject sdo2 = testdao.getObjectFromKey(key);
		Assert.assertEquals(sdo1.getIntValue(), sdo2.getIntValue());

	}

	public void getFromKeyOnly() {
		BaseTask pt = new BaseTask(connection);
		pt.setAssignedUnits(2.2);
		pt.save();
		Key<BaseTask> key = testdao.keyFor(pt);
		BaseTask pt1 = testdao.getObjectFromKey(key);
		Assert.assertEquals(pt.getAssignedUnits(), pt1.getAssignedUnits());
	}

	/**
	 * Simulates Dao not having the class defines in its 'kinds' map
	 */
	// @Test(expectedExceptions = InvalidDomainClassException.class)
	// doesn't really apply now - I don't think
	@Test(enabled = false)
	public void getFromKeyOnly_classUnspecified() {
		SimpleDomainObject sdo1 = new SimpleDomainObject(connection, 101);
		sdo1.setTag("2");
		testdao.save(sdo1);
		Key<SimpleDomainObject> key = testdao.keyFor(sdo1);
		SimpleDomainObject sdo2 = testdao.getObjectFromKey(key);
		Assert.assertEquals(sdo1.getIntValue(), sdo2.getIntValue());
		SimpleDomainObject sdo3 = testdao.getObjectFromKey(key);
		Assert.assertEquals(sdo3.getIntValue(), sdo1.getIntValue());

	}

	public void getFromMixedKeyList() {
		List<Key<? extends DomainObject>> keys = new ArrayList<Key<? extends DomainObject>>();
		BaseTask pt = new BaseTask(connection);
		pt.setAssignedUnits(2.2);
		pt.save();
		keys.add(keyFor(pt));
		IndividualResource ir = new IndividualResource(connection);
		ir.setName("dsowerby");
		ir.save();
		keys.add(keyFor(ir));
		List<? extends DomainObject> results = testdao.getListOf(keys);
		Assert.assertEquals(results.get(0)
				.getClass(), BaseTask.class);
		Assert.assertEquals(results.get(1)
				.getClass(), IndividualResource.class);
	}

	@SuppressWarnings("unchecked")
	public void sharedStructure() throws CycleDetectedException, ChangeInvalidException {
		// first part of the test works because the stored instance has a version of 1
		// while the inMmeory instance has a version of 0 because it has
		// been newly created. This also provides protection in case a new one is created directly in memory
		Key<DAG<Key<BaseTask>>> dependenciesKey = new Key<DAG<Key<BaseTask>>>((Class<? extends DAG<Key<BaseTask>>>) DAG.class, 1);
		DomainDao dao = new DomainDao_BigT(connection);
		DAG<Key<BaseTask>> dependencies = new DAG<Key<BaseTask>>();
		SharedStructureChangeLog changeLog = new SharedStructureChangeLog();
		dependencies.setChangeLog(changeLog);
		dependencies.addVertex(key(1));
		Assert.assertEquals(changeLog.changeCount(), 1);
		dao.saveShared(dependencies, dependenciesKey, changeLog);

		// once changes have been applied and successfully saved, changes should be cleared
		Assert.assertEquals(changeLog.changeCount(), 0);

		// repeat to make sure clean entry second time around
		dependencies.addVertex(key(2));
		dependencies.addEdge(key(1), key(2));
		Assert.assertEquals(changeLog.changeCount(), 2);
		dao.saveShared(dependencies, dependenciesKey, changeLog);
		Assert.assertEquals(changeLog.changeCount(), 0);

	}

	/**
	 * Changes to tasks should also update the dependencies, if the change affects predecessor - successors. This inlcudes the creation of
	 * new atomic tasks
	 * 
	 * @throws PersistenceReferenceException
	 */
	@SuppressWarnings("unchecked")
	public void sharedStructure2() throws PersistenceReferenceException {
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 1);

		BaseTask at1 = new BaseTask(connection);
		BaseTask at2 = new BaseTask(connection);
		BaseTask at3 = new BaseTask(connection);
		Assert.assertNotNull(connection.taskService()
				.getDag(), "Dag should not be null, test setup should create it");

		// both need to be saved before predecessor can be added
		at1.save();
		// changes should have been processed
		// Assert.assertEquals(connection.taskService()
		// .getDag()
		// .changeCount(), 0);
		System.out.println("Change count: " + connection.taskService()
				.getDag()
				.changeCount());
		// saving a new task will add a vertex to the Dag, and therefore up the version
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 2);
		at2.save();
		System.out.println("Change count: " + connection.taskService()
				.getDag()
				.changeCount());
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 3);
		at2.addPredecessor(at1);
		at2.save();
		System.out.println("Change count: " + connection.taskService()
				.getDag()
				.changeCount());
		// dependencies version has also changed because of addPredecessor
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 4);
		// need this later
		at3.save();
		System.out.println("Change count: " + connection.taskService()
				.getDag()
				.changeCount());
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 5);
		// a change which does not affect dependencies
		at2.setPriority(300);
		System.out.println("Change count: " + connection.taskService()
				.getDag()
				.changeCount());
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 5);

		// do a concurrent modification
		// modify the persisted dependencies
		Objectify ofy = ObjectifyService.begin();
		Key<DAG<BaseTask>> dagKey = new Key(DAG.class, new Long(1));
		DAG<BaseTask> dependencies2 = ofy.get(dagKey);
		dependencies2.incrementVersion();
		Assert.assertEquals(dependencies2.getVersion(), 6);
		ofy.put(dependencies2);
		dependencies2 = ofy.get(new Key<DAG>(DAG.class, new Long(1)));
		// persisted DAG has changed version
		Assert.assertEquals(dependencies2.getVersion(), 6);

		// in use dependencies has not changed version
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 5);
		// change to in use dependencies should cause version to go to 7 - the stored version + 1
		at3.addPredecessor(at2);
		at3.save();
		Assert.assertEquals(connection.taskService()
				.getDag()
				.getVersion(), 7);

	}

	private Key<BaseTask> key(long id) {
		return new Key<BaseTask>(BaseTask.class, id);
	}

	/**
	 * Just to shorten a lot of repeated lines
	 * 
	 * @param <T>
	 * @param dob
	 * @return
	 */
	private <T extends DomainObject> Key<T> keyFor(T dob) {
		return testdao.keyFor(dob);
	}
}
